<template>
  <div id="dql">
    <div class="dql-tree">
      <el-card>
        <el-input v-model="filterText" placeholder="请输入系统名称" suffix-icon="el-icon-search" clearable></el-input>
        <el-tree :load="loadNode" lazy :props="defaultProps" @node-click="handleNodeClick" :filter-node-method="filterNode" ref="tree"></el-tree>
      </el-card>
    </div>
    <div class="dql-main">
      <el-card>
        <!-- 内容区头部 -->
        <div class="dql-main-title">
          <span>数据库名： {{ dataName }}</span>
          <span>表总共（个）： {{ tablesNum }}</span>
          <span>视图总共（个）： {{ viewsNum }}</span>
        </div>
        <!-- 分割线 -->
        <el-divider @click="search">查询</el-divider>
        <!-- 查询条件 -->
        <el-form :inline="true" :model="condition" class="demo-form-inline">
          <el-form-item label="表/视图中文名">
            <el-input v-model="condition.chName" placeholder="请输入···" clearable></el-input>
          </el-form-item>
          <el-form-item label="表/视图英文名">
            <el-input v-model="condition.enName" placeholder="请输入···" clearable></el-input>
          </el-form-item>
          <el-form-item label="最近采集日期">
            <el-input v-model="condition.latestDate" placeholder="请输入···" clearable></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="onSearch">查询</el-button>
          </el-form-item>
        </el-form>
        <!-- 表格 -->
        <el-table
          :data="tableData"
          stripe
          border
          height="300"
          style="width: 100%">
          <el-table-column
            type="index"
            label="序号"
            width="100"
            align="center"
            header-align="center">
          </el-table-column>
          <el-table-column
            prop="TABLE_COMMENT"
            label="表/视图中文名"
            align="center"
            header-align="center">
          </el-table-column>
          <el-table-column
            prop="TABLE_NAME"
            label="表/视图英文名"
            align="center"
            header-align="center">
          </el-table-column>
          <el-table-column
            fixed="right"
            label="操作"
            width="200"
            align="center"
            header-align="center">
            <template slot-scope="scope">
              <!-- <el-button @click="handleClick(scope.row)" type="text" size="small">查看</el-button> -->
              <el-button type="text" size="small" @click="handleDetail(scope.row)">详情</el-button>
              <el-button type="text" size="small" @click="handleIncr(scope.row)">增量</el-button>
              <el-button type="text" size="small" @click="handleFull(scope.row)">全量</el-button>
              <el-button type="text" size="small">历史</el-button>
            </template>
          </el-table-column>
        </el-table>
        <!-- 分页 -->
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="pageNum"
          :page-sizes="[5, 10, 15, 20]"
          :page-size="pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="total"
          style="margin-top: 30px;">
        </el-pagination>
      </el-card>
    </div>

    <el-dialog
      title="详情页面"
      :visible.sync="detailVisible">
      <el-row style="margin-bottom: 15px;">
        <el-col :span="12">表/视图名：{{ tableName }}</el-col>
        <el-col :span="12">数据量（万）：{{ recordsLen }}</el-col>
      </el-row>
      <el-row style="margin-bottom: 15px;">
        <el-col :span="12">字段总数：{{ colLen }}</el-col>
        <el-col :span="12">最近采集日期：</el-col>
      </el-row>
      <!-- 表格 -->
      <el-table
        :data="tableDetail"
        stripe
        border
        height="300"
        style="width: 100%">
        <el-table-column
          type="index"
          label="序号"
          width="100"
          align="center"
          header-align="center">
        </el-table-column>
        <el-table-column
          prop="COLUMN_COMMENT"
          label="中文名"
          align="center"
          header-align="center">
        </el-table-column>
        <el-table-column
          prop="COLUMN_NAME"
          label="英文名"
          align="center"
          header-align="center">
        </el-table-column>
        <el-table-column
          prop="DATA_TYPE"
          label="类型"
          align="center"
          header-align="center">
        </el-table-column>
        <el-table-column
          prop="CHARACTER_MAXIMUM_LENGTH"
          label="长度"
          align="center"
          header-align="center">
        </el-table-column>
      </el-table>
    </el-dialog>

    <el-dialog title="增量" :visible.sync="incrVisible" class="incr-export">
      <el-form ref="incrForm" :model="incrForm" label-width="80px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="增量字段">
              <el-input v-model="incrForm.field"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="导出类型">
              <el-select v-model="incrForm.exportType" placeholder="请选择文件类型">
                <el-option
                  v-for="item in fileTypeOptions"
                  :key="item.type"
                  :label="item.desc"
                  :value="item.type">
                </el-option>
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="开始值">
              <el-input v-model="incrForm.start"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="结束值">
              <el-input v-model="incrForm.end"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="文件名" class="export-filename">
          <el-input v-model="incrForm.fileName"></el-input>
          <el-button type="primary" @click="selectFileds">选择导出字段</el-button>
        </el-form-item>
        <el-form-item label="过滤条件">
          <el-input type="textarea" v-model="incrForm.filterCondition"></el-input>
        </el-form-item>
        <div style="text-align: center;">
          <el-button type="primary" @click="incrExport">导出</el-button>
        </div>
        <el-divider>导出详情</el-divider>
        <el-form-item label="进度" class="progress">
          <el-progress :percentage="percentage"></el-progress>
        </el-form-item>
        <el-form-item label="导出日志">
          <el-input type="textarea" v-model="incrForm.log"></el-input>
        </el-form-item>
      </el-form>
      <el-dialog
        width="30%"
        title="选择导出字段"
        :visible.sync="filedVisible"
        append-to-body>
        <el-table
          :data="tableDetail"
          stripe
          border
          height="300"
          style="width: 100%"
          @selection-change="handleSelectionChange">
          <el-table-column
            type="selection"
            width="55">
          </el-table-column>
          <el-table-column
            type="index"
            label="序号"
            width="100"
            align="center"
            header-align="center">
          </el-table-column>
          <el-table-column
            prop="COLUMN_COMMENT"
            label="中文名"
            align="center"
            header-align="center">
          </el-table-column>
          <el-table-column
            prop="COLUMN_NAME"
            label="英文名"
            align="center"
            header-align="center">
          </el-table-column>
          <el-table-column
            prop="DATA_TYPE"
            label="类型"
            align="center"
            header-align="center">
          </el-table-column>
          <el-table-column
            prop="CHARACTER_MAXIMUM_LENGTH"
            label="长度"
            align="center"
            header-align="center">
          </el-table-column>
        </el-table>
        <div slot="footer" class="dialog-footer">
          <el-button type="primary" @click="filedVisible = false">确定</el-button>
        </div>
      </el-dialog>
    </el-dialog>

    <el-dialog title="全量" :visible.sync="fullVisible" class="full-export">
      <el-form ref="fullForm" :model="fullForm" label-width="80px">
        <el-form-item label="文件名">
          <el-input v-model="fullForm.fileName"></el-input>
        </el-form-item>
        <el-form-item label="导出类型" class="export-type">
          <el-select v-model="fullForm.exportType" placeholder="请选择文件类型">
            <el-option
              v-for="item in fileTypeOptions"
              :key="item.type"
              :label="item.desc"
              :value="item.type">
            </el-option>
          </el-select>
          <el-button type="primary" @click="selectFileds">选择导出字段</el-button>
        </el-form-item>
        <el-form-item label="过滤条件">
          <el-input type="textarea" v-model="fullForm.filterCondition"></el-input>
        </el-form-item>
        <div style="text-align: center;">
          <el-button type="primary" @click="fullExport">导出</el-button>
        </div>
        <el-divider>导出详情</el-divider>
        <el-form-item label="进度" class="progress">
          <el-progress :percentage="percentage"></el-progress>
        </el-form-item>
        <el-form-item label="导出日志">
          <el-input type="textarea" v-model="fullForm.log"></el-input>
        </el-form-item>
      </el-form>
      <el-dialog
        width="30%"
        title="选择导出字段"
        :visible.sync="filedVisible"
        append-to-body>
        <el-table
          :data="tableDetail"
          stripe
          border
          height="300"
          style="width: 100%"
          @selection-change="handleSelectionChange">
          <el-table-column
            type="selection"
            width="55">
          </el-table-column>
          <el-table-column
            type="index"
            label="序号"
            width="100"
            align="center"
            header-align="center">
          </el-table-column>
          <el-table-column
            prop="COLUMN_COMMENT"
            label="中文名"
            align="center"
            header-align="center">
          </el-table-column>
          <el-table-column
            prop="COLUMN_NAME"
            label="英文名"
            align="center"
            header-align="center">
          </el-table-column>
          <el-table-column
            prop="DATA_TYPE"
            label="类型"
            align="center"
            header-align="center">
          </el-table-column>
          <el-table-column
            prop="CHARACTER_MAXIMUM_LENGTH"
            label="长度"
            align="center"
            header-align="center">
          </el-table-column>
        </el-table>
        <div slot="footer" class="dialog-footer">
          <el-button type="primary" @click="filedVisible = false">确定</el-button>
        </div>
      </el-dialog>
    </el-dialog>
  </div>
</template>

<script>
  import common from '@/api/common';
  import connect from '@/api/connect';
  import dataQuery from '@/api/dataQuery';
  import gather from '@/api/gather'
  export default {
    name: 'DQL',
    data() {
      return {
        pageNum: 1,
        pageSize: 10,
        total: null,
        // 过滤文本
        filterText: null,
        condition: {},
        tableData: [],
        // 详情弹出框是否显示
        detailVisible: false,
        // el-tree默认属性名
        defaultProps: {
          children: 'children',
          label: 'label'
        },
        // 是否是初始的数据源
        isOriginal: true,
        // 是否切换过数据源
        hasSwitch: false,
        // 数据库名
        dataName: null,
        // 表个数
        tablesNum: null,
        // 视图个数
        viewsNum: null,
        // 表名
        tableName: null,
        tableComment: null,
        currentTable: null,
        // 记录数（数据量）
        recordsLen: null,
        // 字段数
        colLen: null,
        // 详情表格
        tableDetail: null,
        // 增量、全量弹框
        incrVisible: false,
        fullVisible: false,
        filedVisible: false,
        fullForm: {},
        incrForm: {},
        // 可选文件类型
        fileTypeOptions: [],
        // 导出文件类型
        // exportType: null,
        fields: [],
        percentage: 0
      }
    },
    // 监听搜索框文本，当其发生改变时，设置树结构的过滤文本等于这个值
    watch: {
      filterText(val) {
        this.$refs.tree.filter(val);
      }
    },
    methods: {
      // 改变每页显示记录数
      handleSizeChange(val) {
        this.pageSize = val
        this.pageNum = 1
        this.showTablesByCondition()
      },
      // 改变页码
      handleCurrentChange(val) {
        this.pageNum = val
        this.showTablesByCondition()
      },
      isEmpty(obj) {
        if (typeof obj === "undefined" || obj === null || obj === "" || obj === "0" || obj === false || obj === 0 || obj === []) {
            return true;
        } else {
            return false;
        }
      },
      // 分页条件查询数据库表信息
      showTablesByCondition() {
        dataQuery.showTablesByCondition(this.dataName, this.pageNum, this.pageSize, this.condition.chName, this.condition.enName).then(res => {
          console.log(res)
          this.tableData = res.data.tables
          this.total = res.data.total
        })
      },
      onSearch() {
        // 如果用户没有输入最近采集日期，就调用这个接口查询
        if (this.isEmpty(this.condition.latestDate)) {
          this.showTablesByCondition()
        }
      },
      // 展示详情页信息
      showTableDetail() {
        console.log(this.tableName, this.currentTable)
        // 避免重复发送请求
        if (this.currentTable == null || this.tableName != this.currentTable) {
          console.log("show show way")
          dataQuery.showTableDetail(this.dataName, this.tableName).then(res => {
            this.recordsLen = res.data.recordsLen
            this.colLen = res.data.colLen
            this.tableDetail = res.data.detail
            this.currentTable = this.tableName
          })
        }
      },
      // 详情按钮点击事件
      handleDetail(row) {
        this.tableName = row.TABLE_NAME
        this.showTableDetail()
        this.detailVisible = true
      },
      // 增量按钮点击事件
      handleIncr(row) {
        this.tableName = row.TABLE_NAME
        this.tableComment = row.TABLE_NAME
        this.incrVisible = true
        this.percentage = 0
      },
      // 全量按钮点击事件
      handleFull(row) {
        this.tableName = row.TABLE_NAME
        this.tableComment = row.TABLE_NAME
        this.fullVisible = true
        this.percentage = 0
      },
      incrProgress() {
        if (this.percentage < 100) {
          this.percentage += 20
          setTimeout(() => {
            this.incrProgress()
          }, 50);
        }
      },
      // 增量导出
      incrExport() {
        this.incrProgress()
      },
      // 全量导出
      fullExport() {
        const record = {
          chName: this.tableComment,
          enName: this.tableName,
          fieldNum: this.colLen,
          recordNum: this.recordsLen * 10000,
          status: 0,
          type: 0
        }
        console.log(this.tableName, this.fullForm.fileName, this.fullForm.exportType, this.fields)
        dataQuery.fullExport(this.tableName, this.fullForm.fileName, this.fullForm.exportType, this.fields.join(",")).then(res => {
          record.status = 1
          // 获取后端响应头中的文件名
          const contentDisposition = res.headers['content-disposition'];
          const match = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/);
          let fileName = 'exported_file'; // 默认文件名
          if (match && match[1]) {
            fileName = decodeURIComponent(match[1]);
          }
          // 将文件内容封装为 Blob 对象
          const blob = new Blob([res.data], { type: res.headers['content-type'] });
          // 创建临时 URL，并模拟点击下载
          const url = URL.createObjectURL(blob);
          const a = document.createElement('a');
          a.href = url;
          a.download = fileName;
          a.click();
          // 释放临时 URL
          URL.revokeObjectURL(url)
        })
        // 切换回原来的数据源
        setTimeout(() => {
          this.switchOriginal().then(res => {
            if (res) {
              // 在采集表中写入记录
              gather.addRecord(record).then(res => {
                console.log(res)
              })
            }
          })
        }, 1000);
      },
      // 选择导出字段按钮点击事件
      selectFileds() {
        this.filedVisible = true
        this.showTableDetail()
      },
      // 选项发生改变时触发
      handleSelectionChange(val) {
        // 使用map函数遍历选中数组，获取每个元素的字段名组成新数组
        this.fields = val.map(item => item.COLUMN_NAME)
      },
      // 切换回原来的数据源，给方法设置一个返回值，切换数据源要用到
      async switchOriginal() {
        if (!this.isOriginal) {
          return await connect.switchOriginal().then(res => {
            if (res.code == 200) {
              this.isOriginal = true
              console.log("switchOriginal")
              return true
            }
          })
        } else {
          return true
        }
      },
      // 切换数据源并展示
      switchDatasourceAndShow(dataType, name) {
        // 切换数据源
        connect.switchDataSourceByDataTypeAndName(dataType, name).then(res => {
          // 获取数据库名
          this.dataName = res.data
          this.condition = {}
          // 获取数据库信息
          dataQuery.getInfo(this.dataName, dataType, this.pageNum, this.pageSize).then(res => {
            console.log(res)
            this.isOriginal = false
            this.hasSwitch = true
            this.tablesNum = res.data.tablesNum
            this.viewsNum = res.data.viewsNum
            this.tableData = res.data.tables
            this.total = res.data.total
          })
        })
      },
      // 树节点点击事件
      handleNodeClick(data, node) {
        if (node.isLeaf && !data.children) {
          // 如果是第一次点击叶子节点，直接切换数据源
          if (!this.hasSwitch) {
            this.switchDatasourceAndShow(node.parent.data.label, data.label)
          } else {
            // 如果已经切换过数据源，需要先切换到原来的数据源，然后再切换到需要切换的数据源
            this.switchOriginal().then(res => {
              // 切换回原来的数据源成功再接着切换
              if (res) {
                this.switchDatasourceAndShow(node.parent.data.label, data.label)
              }
            })
          } 
        }
      },
      // 树节点懒加载
      loadNode(node, resolve) {
        // 一级节点
        if (node.level === 0) {
          // 请求数据
          common.getDataType().then(res => {
            const data = res.data.map(item => ({
              label: item.label,
              children: []
            }));
            resolve(data); // 将一级节点数据传递给resolve
          });
        } else if (node.level === 1) {
          // 先判断是否需要切换数据源
          this.switchOriginal().then(resp => {
            console.log(resp, "**************")
            if (resp) {
              // 二级节点
              connect.getNameByDataType(node.data.label).then(res => {
                const data = res.data.map(item => ({
                  label: item
                }));
                // 将二级节点数据添加到对应的父节点的 children 属性上
                node.data.children = data
                resolve(data); // 将二级节点数据传递给resolve
              });
            }
          })
          
        } else {
          // 三级及以上节点
          resolve([]); // 没有子节点，传递空数组
        }
        /* const data = []
        // 一级节点
        if (node.level === 0) {
          common.getDataType().then(res => {
            res.data.forEach(item => {
              data.push({
                label: item.label
              })
            })
          })
          // 直接retun一级节点加载不出来并且会报foreach undefined的错误，可能是return时请求还没结束，所以给return设置一个定时器，延迟100ms加载
          setTimeout(() => {
            return resolve(data);
          }, 100);
        } else if (node.level == 1) {
          // 二级节点
          connect.getNameByDataType(node.data.label).then(res => {
            res.data.forEach(item => {
              data.push({
                label: item
              })
            })
          })
          setTimeout(() => {
            return resolve(data);
          }, 100)
        } else {
          // 三级及以上节点
          setTimeout(() => {
            return resolve(data);
          }, 100)
        } */
      },
      // 过滤节点
      filterNode(value, data, node) {
        if (!value) {
          // 如果过滤关键词为空，不进行过滤，所有节点均显示
          return true;
        }
        // 判断节点的 label 是否包含过滤关键词
        if (data.label.indexOf(value) !== -1) {
          // 展开节点
          // node.expanded = true
          // 展开父节点
          node.parent.expanded = true
          return true;
        }
        // 其他节点不进行过滤，全部显示
        return false;
      },
      // 搜索按钮点击事件
      search() {
        // 先切换回初始的数据源，然后查询，查询完成后切换回选中的数据源
        this.switchOriginal().then(res => {
          if (res) {

          }
        })
      }
    },
    mounted() {
      common.getFileType().then(res => {
        this.fileTypeOptions = res.data
      })
    },
    // 进入页面时切换（主要是刷新页面时切换回来）
    beforeRouteEnter (to, from, next) {
      // ...
      connect.switchOriginal().then(res => {
        console.log(res)
        console.log("切换 ok")
      })
      next()
    }
  }
</script>

<style lang="scss" scoped>
  #dql {
    display: flex;
    height: 100%;
    // 左边树结构样式
    .dql-tree {
      width: 250px;
      min-width: 250px;
      margin-right: 10px;
      .el-card {
        height: 100%;
      }
    }
    // 主要内容区样式
    .dql-main {
      flex: 1;
      min-width: 1046px;
      .el-card {
        height: 100%;
        .dql-main-title {
          display: flex;
          justify-content: space-evenly;
          margin-top: 10px;
        }
        .el-divider {
          margin: 45px 0;
        }
        .el-form {
          margin-bottom: 20px;
          .el-input {
            width: 160px;
            margin-right: 20px;
          }
        }
      }
    }
    .el-dialog__wrapper {
      margin-bottom: 30px;
      .progress {
        display: flex;
        align-items: center;
        ::v-deep .el-form-item__content {
          flex: 1;
          // 因为element ui给它设置了80px的左外边距，还是内联样式，样式穿透也解决不了，只能使用!important
          margin-left: 0 !important;
        }
      }
      .el-divider {
        margin: 35px 0 20px;
      }
    }
    .incr-export {
      .el-row {
        ::v-deep .el-col:first-child {
          padding-right: 15px;
        }
      }
      .export-filename {
        ::v-deep .el-form-item__content {
          display: flex;
          .el-button {
            margin-left: 15px;
          }
        }
      }
    }
    .full-export {
      .el-dialog {
        .export-type {
          .el-form-item__content {
            .el-button {
              float: right;
            }
          }
        }
      }
    }
  }
</style>

<style scoped>
  >>>.el-dialog__header {
    border-bottom: 1px solid gray;
    padding-bottom: 20px;
  }
  /* .export-type >>> .el-form-item__content {
    display: flex;
    justify-content: space-between;
  } */
</style>